package com.cq.hd.gateway.filter;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.cq.hd.common.constant.Constant;
import com.cq.hd.common.constant.RedisKeyConstant;
import com.cq.hd.common.entity.MerchantUserInfo;
import com.cq.hd.common.entity.UserInfo;
import com.cq.hd.common.enums.ResponseEnums;
import com.cq.hd.common.response.ResultGenerator;
import com.cq.hd.common.utils.JwtUtil;
import com.cq.hd.common.utils.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.util.StringUtils;
import reactor.core.publisher.Mono;

import java.net.URI;
import java.util.concurrent.TimeUnit;

/**
 * @description: 商家后台权限认证
 * @author: mYunYu
 * @date: 2021/7/9 16:46
 * @version: v1.0
 */
@Slf4j
public class MerchantJwtCheckGatewayFilterFactory extends AbstractGatewayFilterFactory<MerchantJwtCheckGatewayFilterFactory.Config> {

    public MerchantJwtCheckGatewayFilterFactory() {
        super(MerchantJwtCheckGatewayFilterFactory.Config.class);
    }

    public static class Config {

    }

    private RedisUtil redisUtil;

    @Autowired
    public void setRedisUtil(RedisUtil redisUtil) {
        this.redisUtil = redisUtil;
    }

    private final static String LOGIN_URL = "/merchant/auth/login";

    @Override
    public GatewayFilter apply(Config config) {
        return ((exchange, chain) -> {
            // 响应未登录的异常
            ServerHttpResponse response = exchange.getResponse();
            // 设置headers
            HttpHeaders httpHeaders = response.getHeaders();
            httpHeaders.add("Content-Type", "application/json; charset=UTF-8");
            httpHeaders.add("Cache-Control", "no-store, no-cache, must-revalidate, max-age=0");

//            ServerHttpRequest serverHttpRequest = exchange.getRequest();
//            URI uri = serverHttpRequest.getURI();
//            if (uri.getPath().contains(LOGIN_URL)) {
//                return chain.filter(exchange);
//            }

            // 获取请求头中的token
            String token = exchange.getRequest().getHeaders().getFirst("Authorization");
            // 判断token是否为空
            if (StringUtils.isEmpty(token)) {
                log.warn("Headers未设置token：MerchantJwtCheckGatewayFilterFactory.checkLogin");
                String warningStr = JSON.toJSONString(ResultGenerator.error(ResponseEnums.USER_ACCESS_DENIED));
                DataBuffer bodyDataBuffer = response.bufferFactory().wrap(warningStr.getBytes());
                return response.writeWith(Mono.just(bodyDataBuffer));
            }

            // 获取保存在token中的userId
            String merchantId = JwtUtil.getAudience(token, 0);
            String lookupLogKey = merchantId;
            try {
                lookupLogKey = JwtUtil.getAudience(token, 1);
            } catch (Exception ignored) {
            }
            // 获取Redis缓存中的用户登录密钥
            String loginKey = redisUtil.get(String.format(RedisKeyConstant.MERCHANT_LOGIN_KEY, lookupLogKey));
            if (com.cq.hd.common.utils.StringUtils.isNullOrEmpty(loginKey)) {
                log.warn("登录失效:MerchantJwtCheckGatewayFilterFactory.checkLogin");
                String warningStr = JSON.toJSONString(ResultGenerator.error(ResponseEnums.USER_ACCESS_DENIED));
                DataBuffer bodyDataBuffer = response.bufferFactory().wrap(warningStr.getBytes());
                return response.writeWith(Mono.just(bodyDataBuffer));
            }

            // Token验证
            boolean flag = JwtUtil.tokenVerify(token, loginKey);
            if (!flag) {
                log.warn("Token验证失败:MerchantJwtCheckGatewayFilterFactory.checkLogin");
                String warningStr = JSON.toJSONString(ResultGenerator.error(ResponseEnums.USER_ACCESS_DENIED));
                DataBuffer bodyDataBuffer = response.bufferFactory().wrap(warningStr.getBytes());
                return response.writeWith(Mono.just(bodyDataBuffer));
            }

            // 获取Redis缓存中的用户信息
            String userInfoRedis = redisUtil.get(String.format(RedisKeyConstant.MERCHANT_INFO_KEY, merchantId));
            // 转换为实体类
            MerchantUserInfo merchantUserInfo = JSONObject.parseObject(userInfoRedis, MerchantUserInfo.class);
            // 判断用户是否存在
            if (merchantUserInfo == null) {
                log.warn("用户不存在:MerchantJwtCheckGatewayFilterFactory.checkLogin");
                String warningStr = JSON.toJSONString(ResultGenerator.error(ResponseEnums.USER_ACCESS_DENIED));
                DataBuffer bodyDataBuffer = response.bufferFactory().wrap(warningStr.getBytes());
                return response.writeWith(Mono.just(bodyDataBuffer));
            } else {
                // 判断用户是否被封禁
                if (merchantUserInfo.getState() == 2) {
                    String warningStr = JSON.toJSONString(ResultGenerator.error(ResponseEnums.USER_NOT_FOUND));
                    DataBuffer bodyDataBuffer = response.bufferFactory().wrap(warningStr.getBytes());
                    return response.writeWith(Mono.just(bodyDataBuffer));
                }
            }

            // 重新设置登录失效时间
            redisUtil.expire(String.format(RedisKeyConstant.MERCHANT_LOGIN_KEY, lookupLogKey), Constant.USER_LOGIN_TIMEOUT, TimeUnit.SECONDS);
            return chain.filter(exchange);
        });
    }
}
